/*{ include }*/
#include "threadwrapper.h"
#include "threadcancel.h"
/*{ end }*/

/*{ core thread wrapper }*/
int startThread(pthread_t* threadId, void* (*start)(void*), void* arg) {
    int ret = 0;
    pthread_attr_t attr;
    pthread_attr_init (&attr);  // Initialize thread-attributes with default values

    if (pthread_create(threadId, &attr, start, arg) < 0) {
        ret = -1;
    }
    pthread_attr_destroy(&attr);  // Destroy the thread-attributes

    return ret;
}

int joinThread(pthread_t& threadId, void** retValue) {
    int ret = 0;
    
    return pthread_join(threadId, retValue);
}


int cancelThread(pthread_t& threadId) {
    return pthread_cancel(threadId);
}

/*{ end }*/

/*{ thread wrapper }*/

int startCounterThread(pthread_t* threadId, std::string name, int max, int delay) {
    ThreadData* threadData = new ThreadData(name, max, delay);  // Initialize data

    return startThread(threadId, startCancelableCounterthread, threadData);
}

int joinCounterThread(pthread_t& threadId, int* retValue) {
    int ret = 0;
    void* p_retValue;

    if (joinThread(threadId, &p_retValue) == 0) {  // Wait for thread 2
        if (p_retValue == PTHREAD_CANCELED) {
            return -2;
        }
        *retValue = *(int*) p_retValue;              // and absorb its ret-value
        delete (int*) p_retValue;  // Destroy memory allocated in startCounterThread()
    } else {
        ret = -1;
    }
    return ret;
}
/*{ end }*/